﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LibFiltr
{
    public class GaussianSeparableFilter: SeparableFilter
    {
        protected double _deviation;

        public GaussianSeparableFilter(int radius, double deviation = 1.0) :
            base(radius)
        {
            _deviation = deviation;
            double kernelSum = 0.0;
            double coeff = 1 / Math.Sqrt(2 * Math.PI * Math.Pow(deviation, 2));

            for (int i = -radius; i <= radius; i++)
            {
                double ePow = -Math.Pow(i, 2) / (2 * Math.Pow(_deviation, 2));
                _kernel_h[i+radius] = _kernel_v[i+radius] = coeff * Math.Exp(ePow);
                kernelSum += _kernel_h[i+radius];
            }
            // normalization
            //for (int i = 0; i < SizeHorizontal(); i++)
            //        _kernel_h[i] = _kernel_v[i] /= kernelSum;
            for (int i = 0; i < SizeHorizontal; i++)
                _kernel_h[i] = _kernel_v[i] /= kernelSum;
        }
    }

    public class GaussianFilter: KernelFilter
    {
        protected double _deviation;
        public GaussianFilter(int radius, double deviation = 1.0) :
            base(radius)
        {
            _deviation = deviation;
            double kernelSum = 0.0;
            double coeff = 1 / (2 * Math.PI * Math.Pow(deviation, 2));
            double twoDeviationSquare = 2 * Math.Pow(_deviation, 2);

            //Console.WriteLine(coeff);
            for (int i = -_radius; i <= _radius; i++)
                for (int j = -_radius; j <= _radius; j++)
                {
                    //double ePow = -(Math.Pow(j, 2) + Math.Pow(i, 2)) / (2 * Math.Pow(_deviation, 2));
                    double ePow = -(Math.Pow(j, 2) + Math.Pow(i, 2)) / twoDeviationSquare;
                    _kernel[i + _radius, j + _radius] = coeff * Math.Exp(ePow);
                    kernelSum += _kernel[i + _radius, j + _radius];
                }
            for (int i = -_radius; i <= _radius; i++)
                for (int j = -_radius; j <= _radius; j++)
                    _kernel[i + _radius, j + _radius] /= kernelSum;
        }
    }
}
